﻿/**************************************************************************
创建时间:	2019.3.26
作	  者:	张存
邮 	  箱:	zhangcunliang@126.com

Copyright (c) zhcun.cn

描	述： aes 加解密的实现
记	录：
    多语言差异参考：https://my.oschina.net/Jacker/blog/86383?p=2
***************************************************************************/
using ASmile.Extend;
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;

namespace ASmile.Helpers
{
    /// <summary>
    /// aes 加密的相关操作
    /// </summary>
    public class DEncryptAES
    {
        /// <summary>
        /// 如果key或iv长度不为16字节则重置长度
        /// </summary>
        static void ResetKeyLength(ref byte[] key)
        {
            if (key.Length < 16)
            {
                var dest = new byte[16];
                key.CopyTo(dest, dest.Length - key.Length);
                key = dest;
            }
            else if (key.Length > 16)
            {
                var dest = new byte[16];
                Array.Copy(key, dest, 16);
                key = dest;
            }
        }
        /// <summary>
        /// 对指定字符串进行aes加密，指定key与iv，返回base64字符串
        /// </summary>
        public static string Encrypt(string toEncrypt, string key, string iv)
        {
            if (string.IsNullOrEmpty(toEncrypt) || string.IsNullOrEmpty(key))
            {
                return toEncrypt;
            }
            byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
            ResetKeyLength(ref keyArray);
            byte[] ivArray = UTF8Encoding.UTF8.GetBytes(iv);
            ResetKeyLength(ref ivArray);
            byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);
            RijndaelManaged rDel = new RijndaelManaged();
            rDel.Key = keyArray;
            rDel.IV = ivArray;
            rDel.Mode = CipherMode.CBC;
            rDel.Padding = PaddingMode.Zeros;
            ICryptoTransform cTransform = rDel.CreateEncryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
            return Convert.ToBase64String(resultArray, 0, resultArray.Length);
        }
        /// <summary>
        /// 对指定字符串进行aes加密，指定key，iv与key一致，返回base64字符串
        /// </summary>
        public static string Encrypt(string toEncrypt, string key)
        {
            return Encrypt(toEncrypt, key, key);
        }
        /// <summary>
        /// 对指定字符串进行解密
        /// </summary>
        public static byte[] DecryptBytes(string toDecrypt, string key, string iv)
        {
            byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);
            return DecryptBytes(toEncryptArray, toEncryptArray.Length, key, iv);
        }
        /// <summary>
        /// 对指定字节数组进行aes解密，指定key与iv，返回base64字符串
        /// toEncryptArray 必须为Base64字符转换的数组
        /// </summary>
        public static byte[] DecryptBytes(byte[] toEncryptArray, int arrayLength, string key, string iv)
        {
            //try
            //{
            if (iv.IsEmpty()) iv = key;

            if (toEncryptArray == null || toEncryptArray.Length == 0)
            {
                return new byte[] { };
            }
            byte[] keyArray = Encoding.UTF8.GetBytes(key);
            ResetKeyLength(ref keyArray);
            byte[] ivArray = Encoding.UTF8.GetBytes(iv);
            ResetKeyLength(ref ivArray);
            //byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);

            RijndaelManaged rDel = new RijndaelManaged();
            rDel.Key = keyArray;
            rDel.IV = ivArray;
            rDel.Mode = CipherMode.CBC;
            //rDel.Padding = PaddingMode.Zeros;
            rDel.Padding = PaddingMode.None;
            ICryptoTransform cTransform = rDel.CreateDecryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, arrayLength);
            return resultArray;
            //}
            //catch (Exception ex)
            //{
            //    var bsHex = BytesHelper.ByteArrToHex(toEncryptArray, false);
            //    //var toDecrypt = Encoding.UTF8.GetString(toEncryptArray); \ncontent:{toDecrypt}
            //    LogHelper.LogObj.Fatal($"aes解密发生异常, \nkey:\n{key}\ncontentHex:\n{bsHex}\n", ex);
            //    throw ex;
            //}
        }

        public static byte[] DecryptBytes(string toDecrypt, string key)
        {
            return DecryptBytes(toDecrypt, key, key);
        }
        public static string Decrypt(string toDecrypt, string key, string iv)
        {
            if (string.IsNullOrEmpty(toDecrypt) || string.IsNullOrEmpty(key))
            {
                return toDecrypt;
            }
            var resultArray = DecryptBytes(toDecrypt, key, iv);
            var r = Encoding.UTF8.GetString(resultArray);
            r = r.Replace("\0", "");
            return r;
        }
        /// <summary>
        /// 对指定字符串进行aes解密，指定key，iv与key一致，返回base64字符串
        /// </summary>
        public static string Decrypt(string toDecrypt, string key)
        {
            return Decrypt(toDecrypt, key, key);
        }
    }
}